#include "Exception.h"

#include <cstring>
#include <cstdlib>
#include <cstdio>

using namespace std;

namespace demolib
{

//异常信息从栈空间拷贝到堆空间，拼接异常信息地址空间（文件名和行号）
void Exception::init(const char* message, const char* file, int line)
{
    if(message != nullptr)
        m_message = strdup(message);

    if(file != nullptr)
    {
        char sl[16] = {0};

        snprintf(sl, sizeof(sl), "%d", line);

        //malloc内存申请失败返回NULL，不建议使用nullptr与NULL混用
        m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
        if(m_location != NULL)
        {
            m_location = strcpy(m_location, file);
            m_location = strcat(m_location, ":");
            m_location = strcat(m_location, sl);
        }
    }
    else
    {
        m_location = nullptr;
    }
}

Exception::Exception(const char* message)
{
    init(message, nullptr, 0);
}

Exception::Exception(const char* file, int line)
{
    init(nullptr, file, line);
}

Exception::Exception(const char* message, const char* file, int line)
{
    init(message, file, line);
}

//拷贝构造函数，实现堆到堆的深拷贝
Exception::Exception(const Exception& e)
{
    m_message = strdup(e.m_message);
    m_location = strdup(e.m_location);
}

Exception& Exception::operator= (const Exception& e)
{
    if(this != &e)
    {
        free(m_message);
        free(m_location);

        m_message = strdup(e.m_message);
        m_location = strdup(e.m_location);    
    }
    return *this;
}

const char* Exception::message()const
{
    return m_message;
}

const char* Exception::location()const
{
    return m_location;
}

Exception::~Exception()
{
    free(m_message);
    free(m_location);
}

}
